#include "../include/variant.h"
#include <cstdio>
#include "table/TableCodec.h"

namespace qb {
namespace proto {

FieldCollector* VariantRecord::FindCollector(const std::string& name)const 
	{
		if (table_codec_){
			return table_codec_->FindCollector(name, true);
		}
		return NULL;
	}

FieldCollector* VariantRecord::GetCollector(const std::string& name)
	{
		if (table_codec_){
			return table_codec_->GetCollector(name, true);
		}
		return NULL;
	}
VariantRecord::VariantRecord(TableCodec* table_codec, int row)
	: table_codec_(table_codec)
	, row_(row) {
}

bool VariantRecord::setDouble(const std::string& name, double value) {
	if (name.empty()) {
		return false;
	}
	FieldCollectorPtr collector = GetCollector(name);
	if (collector == NULL) {
		return false;
	}
	collector->AddValue(row_, VarValue(value));
	return true;
}

bool VariantRecord::setString(const std::string& name, const std::string& value) {
	if (!name.empty()) {
		VarValue vv(table_codec_->AllocString(value.c_str(), value.size()),value.size());
		FieldCollectorPtr collector = GetCollector(name);
		if (collector == NULL) {
			return false;
		}
		collector->AddValue(row_, vv);
		return true;
	}
	return false;
}

bool VariantRecord::setInt64(const std::string& name, int64_t value) {
	if (!name.empty()) {
		FieldCollectorPtr collector = GetCollector(name);
		if (collector == NULL) {
			return false;
		}
		collector->AddValue(row_, VarValue((i64)value));
		return true;
	}
	return false;
}

bool VariantRecord::setUint64(const std::string& name, uint64_t value) {
	if (!name.empty()) {
		FieldCollectorPtr collector = GetCollector(name);
		if (collector == NULL) {
			return false;
		}
		collector->AddValue(row_, VarValue((ui64)value));
		return true;
	}
	return false;
}

bool VariantRecord::getDouble(const std::string& name, double& value)const {
	if (name.empty()) {
		return false;
	}

	FieldCollectorPtr collector = FindCollector(name);
	if (collector == NULL) {
		return false;
	}

	const VarValue& val = collector->GetValue(row_);
	if (val.type != kExpectTypeDouble) {
		return false;
	}

	value = val.d;
	return true;
}

bool VariantRecord::refString(const std::string& name, const char *& value, size_t &size)const{
	if (name.empty()) {
		return false;
	}

	FieldCollectorPtr collector = FindCollector(name);
	if (collector == NULL) {
		return false;
	}

	const VarValue& val = collector->GetValue(row_);
	if (val.type != kExpectTypeString) {
		return false;
	}

	value = val.str.ptr;
	size = val.str.len;
	return true;
}

bool VariantRecord::getString(const std::string& name, std::string& value)const{
	if (name.empty()) {
		return false;
	}

	FieldCollectorPtr collector = FindCollector(name);
	if (collector == NULL) {
		return false;
	}

	const VarValue& val = collector->GetValue(row_);
	if (val.type != kExpectTypeString) {
		return false;
	}

	value = std::string(val.str.ptr, val.str.len);
	return true;
}

bool VariantRecord::getInt64(const std::string& name, int64_t& value)const {
	if (name.empty()) {
		return false;
	}

	FieldCollectorPtr collector = FindCollector(name);
	if (collector == NULL) {
		return false;
	}

	const VarValue& val = collector->GetValue(row_);
	if (val.type != kExpectTypeInt) {
		return false;
	}

	value = val.i;
	return true;
}

bool VariantRecord::getInt32(const std::string& name, int &value)const{
	int64_t ivalue = 0;
	if (getInt64(name, ivalue))
	{
		value = ivalue;
		return true;
	}
	return false;
}

bool VariantRecord::getUint64(const std::string& name, uint64_t& value)const {
	if (name.empty()) {
		return false;
	}

	FieldCollectorPtr collector = FindCollector(name);
	if (collector == NULL) {
		return false;
	}

	const VarValue& val = collector->GetValue(row_);
	if (val.type != kExpectTypeInt) {
		return false;
	}

	value = val.u;
	return true;
}


}
}
